home *** CD-ROM | disk | FTP | other *** search
- /*
- * The original copyright owners of the accompanying source code files have
- * agreed to place such code into the public domain. Accordingly, anyone
- * who receives or obtains a copy of such source code is freely entitled to
- * reproduce, use and otherwise exploit such code (including the right to
- * make derivative works), at his/her own risk and expense, without any
- * obligation or liability to the original copyright owners.
- *
- * We would appreciate (but do not require) that the following message be
- * included in any derivative works:
- *
- * "Portions of this program were developed by Peter Broadwell, Rob Myers
- * and Robin Schaufler while working in Silicon Valley."
- *
- * The accompanying source code files and related documentation materials
- * are distributed on an "AS IS" basis, without any warranties or
- * guarantees of any kind. All implied warranties, including the implied
- * warranties of merchantability and of fitness for any particular purpose,
- * are expressly disclaimed.
- */
- #include <stdio.h>
- #include <ctype.h>
- #include "gl.h"
- #include "math.h"
- #include "geom.h"
- #include "colors.h"
- #include "objIds.h"
- #include "class.h"
- #include "classIds.h"
- #include "selectors.h"
- #include "mbox.h"
- #include "individual.h"
- #include "behavior.h"
- #include "doers.h"
- #include "panel.h"
- #include "voxel.h"
-
- extern individual *us;
- extern long masterClock;
-
- extern subscr *findvars();
- extern behavior chameleonTemplate;
- extern behavior expanderTemplate;
- extern behavior advancerTemplate;
- extern behavior surfDieTemplate;
- extern behavior wideyeTemplate;
-
- Dot(p1,p2)
- register point *p1, *p2;
- {
- return (p1->x * p2->x + p1->y * p2->y + p1->z * p2->z);
- }
-
- float
- fDot(p1,p2)
- register fpoint *p1, *p2;
- {
- return (p1->x * p2->x + p1->y * p2->y + p1->z * p2->z);
- }
-
- float
- fiDot(p1,p2)
- register fpoint *p1;
- register point *p2;
- {
- return (p1->x * p2->x + p1->y * p2->y + p1->z * p2->z);
- }
-
- float
- fiCrossHack(p1,p2) /* returns only z component */
- register fpoint *p1;
- register point *p2;
- {
- return (p1->x * p2->y - p1->y * p2->x);
- }
-
- normalize(p)
- register fpoint *p;
- {
- register float mag;
-
- mag = sqrt(fabs(p->x * p->x + p->y * p->y + p->z * p->z));
- if(mag == 0.0) {
- return 0;
- }
-
- p->x = p->x / mag;
- p->y = p->y / mag;
- p->z = p->z / mag;
- /*******/
- return 1;
- }
-
- vtoh(h,v)
- register fpoint *h;
- register point *v;
- {
- register float mag;
-
- mag = sqrt((float)(abs(v->x * v->x + v->y * v->y + v->z * v->z)));
- if(mag == 0.0) {
- return 0;
- }
-
- h->x = v->x / mag;
- h->y = v->y / mag;
- h->z = v->z / mag;
- return 1;
- }
-
- extern point bowlRadius;
-
- /*
- ROBS_SWIM is one of those seat of the pants heuristic algorythms
- that seems to work better than the "cleaner" version peter tried.
- This is an area for endless experimentation, have fun.
- Also used in doerMethods.c as an inline define to keep the
- Makefile simple.
- */
- #define ROBS_SWIM
- #ifdef ROBS_SWIM
- /*
- * make the target individual swim to the next position.
- */
- behavior *
- swimTo(self, argtype, target)
- behavior *self;
- int argtype;
- register individual *target;
- {
- register float rspeed;
- register float rad, dot, ratio = 0.0;
-
- rad = sqrt(fabs((float)(target->position.x * target->position.x
- + target->position.y * target->position.y )));
- if(rad > bowlRadius.x) { /* out there */
- ratio = (rad/bowlRadius.x) - 1.0;
- /* going out ? */
- if((dot = fiDot(&target->heading,&target->position))
- > -(rad-abs(target->position.x)/8)) {
- static point2df deltahead;
- /* swerve witch way ? */
- if(fiCrossHack(&target->heading,&target->position) > 0.0) {
- deltahead.x = ratio/4.0;
- } else {
- deltahead.x = -ratio/6.0;
- }
- changeHead(target,sizeof(point2df), &deltahead);
- }
- }
- rspeed = target->speed - 2.0 * ratio * target->speed;
- target->velocity.x = target->heading.x * rspeed;
- target->velocity.y = target->heading.y * rspeed;
- if(fabs(target->heading.z) > 0.3) {
- target->heading.z = 0.3 * sign(target->heading.z);
- normalize(&target->heading);
- }
- target->velocity.z = target->heading.z * rspeed;
- target->position.x += target->velocity.x;
- target->position.y += target->velocity.y;
- target->position.z += target->velocity.z;
- if(target->position.z > bowlRadius.z || target->position.z < -bowlRadius.z)
- target->heading.z *= -1;
-
- /********
- printf("swimTo:");
- printf(" speed=%g", target->speed);
- printf(" heading=%g,%g,%g",
- target->heading.x, target->heading.y, target->heading.z);
- printf(" velocity=%d,%d,%d",
- target->velocity.x, target->velocity.y, target->velocity.z);
- printf("\n");
- /********/
-
- return self;
- }
- /*
- * make the target individual swim to the next position.
- */
- behavior *
- rrswimTo(self, argtype, target) behavior *self;
- int argtype;
- register individual *target;
- {
- extern point bowlRadius;
- register long dim = 0,*velocity,*position,*bowlsize,*maxvelocity;
- int gumbyFlag = FALSE;
- int abspos, minmax, bowleffect;
- swerverVars *targetVars;
-
- if (targetVars = (swerverVars *)target->curVars) {
- velocity = &target->velocity.x;
- position = &target->position.x;
- bowlsize = &bowlRadius.x;
- maxvelocity = &targetVars->maxvelocity.x;
- minmax = min(maxvelocity[0], maxvelocity[1]);
-
- target->velocity.x = target->heading.x * target->speed;
- target->velocity.y = target->heading.y * target->speed;
- target->velocity.z = target->heading.z * target->speed;
-
- bowleffect = (*bowlsize)-((*bowlsize) >> 2); /* 3/4 bowl radius */
- /* for each dimension:*/
- for(dim = 0; dim < 3;
- dim++,velocity++,position++,bowlsize++,maxvelocity++)
- {
- abspos = abs(*position);
- if(bowleffect < abspos) {
- /* going out slow */
- if(abs(*velocity) <= max(10, target->speed/16)
- && sign(*velocity) == sign(*position)) {
- *velocity = -(*velocity);
- gumbyFlag = TRUE;
- } else { /* full speed */
- *velocity = *velocity *(*bowlsize+1 - min(*bowlsize,abspos))
- / (*bowlsize - bowleffect);
- }
- if(! *velocity)
- *velocity = -sign(*position) *
- max(10, target->speed/16);
- }
-
- /* keep z much smaller than x and y */
- if(dim == 2) {
- *velocity = sign(*velocity) *
- min(abs(*velocity),
- min(abs(target->velocity.x),
- abs(target->velocity.y))
- * *maxvelocity / minmax);
- }
- *position += *velocity;
- }
- /* adjust heading to match possibly-changed velocity */
- if(gumbyFlag) vtoh(&target->heading, &target->velocity);
-
- /********/
- printf("swimTo:");
- printf(" speed=%g", target->speed);
- printf(" heading=%g,%g,%g",
- target->heading.x, target->heading.y, target->heading.z);
- printf(" velocity=%d,%d,%d",
- target->velocity.x, target->velocity.y, target->velocity.z);
- printf("\n");
- /********/
- }
- else fprintf(stderr, "swimTo: can't find instance variables\n");
-
- return self;
- }
- #else /* ROBS_SWIM */
- /*
- * make the target individual swim to the next position.
- */
- behavior *
- rswimTo(self, argtype, target)
- behavior *self;
- int argtype;
- register individual *target;
- {
- extern point bowlRadius;
- register int dim = 0, *velocity, *position, *bowlsize, *maxvelocity;
- int abspos, minmax;
- swerverVars *targetVars;
-
- if (targetVars = (swerverVars *)target->curVars) {
- velocity = &target->velocity.x;
- position = &target->position.x;
- bowlsize = &bowlRadius.x;
- maxvelocity = &targetVars->maxvelocity.x;
- minmax = min(maxvelocity[0], maxvelocity[1]);
-
- /* for each dimension:*/
- for(dim = 0; dim < 3;
- dim++, velocity++, position++, bowlsize++, maxvelocity++)
- {
- abspos = abs(*position);
- /* if position is more than halfway to side of bowl */
- if((*bowlsize) >> 1 < abspos) {
- if(abs(*velocity) <= min(10,(*maxvelocity)>>4)
- && sign(*velocity) == sign(*position)) {
- *velocity = -(*velocity);
- } else {
- *velocity = (sign(*velocity) * *maxvelocity *
- ((*bowlsize) - abspos)) /
- ((*bowlsize) >> 1);
- }
- if(! *velocity)
- *velocity = -sign(*position) *
- min(10,(*maxvelocity)>>4);
- }
- /* keep z much smaller than x and y */
- if(dim == 2) {
- *velocity = sign(*velocity) *
- min(abs(*velocity),
- min(abs(target->velocity.x),
- abs(target->velocity.y))
- * *maxvelocity / minmax);
- }
- *position += *velocity;
- }
- }
- else printf(stderr, "swimTo: can't find instance variables\n");
-
- return self;
- }
- #endif /* ROBS_SWIM */
-
- #ifdef PETERS_SWIM
- /*
- * make the target individual swim to the next position.
- */
- behavior *
- pswimTo(self, argtype, target)
- behavior *self;
- int argtype;
- register individual *target;
- {
- float rad;
- static point2df veer = { 0.0, PI/3.0, };
- float sp = target->speed;
- fpoint *hd = &target->heading;
- point *v = &target->velocity;
- point *p = &target->position;
- static int sizebowl = 3000;
-
- v->x = sp * hd->x;
- v->y = sp * hd->y;
- v->z = sp * hd->z;
-
- p->x = v->x + p->x;
- p->y = v->y + p->y;
- p->z = v->z + p->z;
-
- rad = sqrt(fabs((float)(p->x * p->x + p->y * p->y)));
-
- printf("rad = %g\n", rad);
- if(rad > sizebowl) {
- p->x += p->x * 0.9;
- p->y += p->y * 0.9;
- p->z += p->z * 0.9;
- puts("pre veer ");dumpIndiv(target);
- Msg(target, NEWHEADING, sizeof(point2df), &veer);
- }
-
-
- printf("0x%x at ", target);puts("swimTo end");dumpIndiv(target);
- return self;
- }
- #endif /* PETERS_SWIM */
-
- dumpIndiv(s)
- individual *s;
- {
- printf("pos = %d %d %d\n", s->position.x, s->position.y, s->position.z);
- printf("vel = %d %d %d\n", s->velocity.x, s->velocity.y, s->velocity.z);
- printf("head = %g %g %g\n", s->heading.x, s->heading.y, s->heading.z);
- printf("speed = %g\n", s->speed);
- }
-